﻿using ConsoleApp1.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace ConsoleApp1
{


    class Program
    {
        static void Main(string[] args)
        {

            var s = new Program();
            Task.Run(async () =>
            {
                writeLine("开始");
                //s.clear();
                // s.loopHandleAsync(110000, 55968)
                //442100 东沙群岛排除,710000 台湾省排除
                int[] exclude = { 442100, 710000 };
                writeLine("查找省级缺失对象");
                var list = s.needAction("province");
                var provinces = list.Where((item) => exclude.Contains(item.adcode)).ToList();
                foreach (var province in provinces)
                {
                    await s.loopHandleAsync(province.adcode, province.areaId);
                }
                writeLine("查找市级缺失对象");
                list = s.needAction("city");
                var citys = list.Where((item) => exclude.Contains(item.adcode)).ToList();
                foreach (var city in citys)
                {
                    await s.loopHandleAsync(city.adcode, city.areaId);
                }
                writeLine("完成");
            });
            while (true)
            {
                Console.ReadLine();
            }

        }

        static string[] keys = new string[]{"3387f2aae76ebd4f915de5ade19634dc", "806178332e93277d48d196c6981d3598", "35ea21e11d1a80d9ef41014a1b8513b4",
    "27b4b0aeb8dd4c32614f13d3e3fd866f", "09ee92217380c74c07119fbc31191078", "188237b34dde0db2acdb536db5763df9",
    "5f9f8a5b20757d48f26cce0125f3f24d", "93495dcc4cc8085550fff629c000616e", "fb206e2bb6c03d6d021de271c64b3d3d" };


        static void writeLine(string text, Color color = default)
        {
            if (color == default) color = Color.White;
            Colorful.Console.WriteLine(text, color);
        }

        async Task<List<District>> serachFromAMap(int adcode)
        {
            while (true)
            {

                try
                {
                    HttpClient httpClient = new HttpClient();
                    Random random = new Random();
                    var index = random.Next(0, keys.Length - 1);
                    string key = keys[index];
                    string url = $"http://restapi.amap.com/v3/config/district?key={key}&subdistrict=1&extensions=all&keywords={adcode}";
                    var httpResponse = await httpClient.GetAsync(url);
                    if (httpResponse.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        var json = await httpResponse.Content.ReadAsStringAsync();
                        json = json.Replace("\"citycode\":[]", "\"citycode\":0");//fix data error
                        var response = JsonConvert.DeserializeObject<Response>(json, new JsonSerializerSettings()
                        {
                            Error = (object sender, ErrorEventArgs errorArgs) =>
                            {
                                errorArgs.ErrorContext.Handled = true;
                                //Console.WriteLine(errorArgs.ToString()); 
                            },
                        });
                        if (response.districts.Count > 0)
                        {
                            return response.districts;
                        }
                    }

                }
                catch (Exception ex)
                {
                    writeLine(ex.ToString());
                }
            }
        }


        SQLiteConnection getConn()
        {
            SQLiteConnection connection = new SQLiteConnection("DataSource=../../../china_gis.db");
            connection.Open();
            return connection;
        }


        /// <summary>
        /// areaId,adcode
        /// </summary>
        /// <param name="level"></param>
        /// <returns></returns>
        List<(int areaId, int adcode)> needAction(string level)
        {
            using (SQLiteConnection connection = getConn())
            {
                using (var command = connection.CreateCommand())
                {
                    List<(int, int)> list = new List<(int, int)>();
                    command.CommandText = $"SELECT * from (select *,(select count(1) from china_area as c where c.parentId=china_area.areaId) as childCount from china_area where level='{level}') as t where t.childCount<1";
                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            list.Add((Convert.ToInt32(reader["areaId"]), Convert.ToInt32(reader["adcode"])));

                        }
                    }
                    return list;
                }
            }
        }
        int insertData(District item, int parentId)
        {

            using (SQLiteConnection connection = getConn())
            {

                using (var tran = connection.BeginTransaction())
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandText = "insert into china_area(adcode,center,citycode,level,name,polyline,parentId) values (@adcode,@center,@citycode,@level,@name,@polyline,@parentId)";
                        command.Parameters.AddWithValue("adcode", item.adcode);
                        command.Parameters.AddWithValue("center", item.center);
                        command.Parameters.AddWithValue("citycode", item.citycode);
                        command.Parameters.AddWithValue("level", item.level);
                        command.Parameters.AddWithValue("name", item.name);
                        command.Parameters.AddWithValue("polyline", "");
                        command.Parameters.AddWithValue("parentId", parentId);
                        command.Transaction = tran;
                        command.ExecuteNonQuery();
                    }

                    using (var command2 = connection.CreateCommand())
                    {
                        command2.CommandText = "select last_insert_rowid() as areaId";

                        command2.Transaction = tran;


                        var result = command2.ExecuteScalar();
                        if (result != null)
                        {
                            var areaId = Convert.ToInt32(result);
                            tran.Commit();
                            return areaId;
                        }
                        else
                        {
                            return 0;
                        }
                    }
                }
            }
        }

        void updatePolyline(int areaId, string polyline)
        {
            using (SQLiteConnection connection = getConn())
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "update china_area set  polyline=@polyline   where areaId=@areaId";
                    command.Parameters.AddWithValue("polyline", polyline);
                    command.Parameters.AddWithValue("areaId", areaId);
                    command.ExecuteNonQuery();
                }
            }
        }

        void clear()
        {
            using (SQLiteConnection connection = getConn())
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "delete from china_area";
                    command.ExecuteNonQuery();
                }
            }
        }


        async Task loopHandleAsync(int adcode, int parentId)
        {
            var districts = await this.serachFromAMap(adcode);
            for (var i = 0; i < districts.Count; i++)
            {
                var district = districts[i];
                var hasNext = district.districts.Count < 2 || district.districts.Select(s => s.adcode).GroupBy(s => s).Count() > 1;
                writeLine($"解析【{district.name}】的数据,共计{district.districts.Count}条,级别为{district.level}", Color.Blue);
                var noChild = new List<string>();
                for (int j = 0; j < district.districts.Count; j++)
                {
                    var item = district.districts[j];
                    writeLine($"处理【{item.name}】的数据[{j}/{district.districts.Count}]");

                    var insertedId = insertData(item, parentId);
                    if (insertedId < 1)
                    {

                        writeLine($"${JsonConvert.SerializeObject(item)}此数据写入失败", Color.Red);

                    }
                    if (hasNext && insertedId > 0)
                    {
                        writeLine($"查询【{item.name}】的数据", Color.Green);
                        await this.loopHandleAsync(item.adcode, insertedId);
                    }
                    else
                    {
                        noChild.Add(item.name);
                    }
                }
                if (noChild.Count > 0)
                    writeLine($"查询【{string.Join(",", noChild)}】的数据的下级数据无需查询");
                if (district.polyline != null && district.polyline != "")
                {
                    if (parentId > 0)
                    {
                        writeLine($"更新【{district.name}】的polyline", Color.Yellow);
                        //写入polyline数据
                        updatePolyline(parentId, district.polyline);
                    }

                }

            }

        }


    }
}
